﻿﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace VideoClipNameHelper
{
    //================================================================
    public class MediaDirectory
    {
        public bool ArgumentIsDirectory { get; internal set; }
        public string DirectoryName { get; internal set; }
        public List<MediaFile> MediaFiles;
        public Dictionary<string, string> HintData;

        public MediaDirectory()
        {
            ArgumentIsDirectory = false;
            DirectoryName = "";
            MediaFiles = new List<MediaFile>();
            HintData = new Dictionary<string, string>();
        }
        public MediaDirectory(MediaDirectory md)
        {
            ArgumentIsDirectory = md.ArgumentIsDirectory;
            DirectoryName = md.DirectoryName;
            MediaFiles = new List<MediaFile>(md.MediaFiles);
            HintData = new Dictionary<string, string>(md.HintData);
        }
        public MediaDirectory(MediaDirectory md, List<MediaFile> mf)
        {
            ArgumentIsDirectory = md.ArgumentIsDirectory;
            DirectoryName = md.DirectoryName;
            MediaFiles = new List<MediaFile>(mf);
            HintData = new Dictionary<string, string>(md.HintData);
        }
    }
    //================================================================
    public class MediaFile
    {
        public string OriginalFile { get; set; }
        public string ResolvedFile { get; set; }
        //
        public override string ToString()
        {
            return "[" + OriginalFile + "] [" + ResolvedFile + "]";
        }
    }
    //================================================================
    public class DirectoryCache
    {
        private static List<string> mediaExt = new List<string>(){ ".AVI", ".MKV", ".MP4", ".VOB", ".FLV" };
        //
        private static Queue<MediaDirectory> MDQ = new Queue<MediaDirectory>(3);
        //
        //
        /// <summary>
        /// jeżeli parametr to DIRECTORY
        /// zwracamy wszystkie medialne pliki z katalogu
        /// jeżeli parametr to PLIK
        /// zwracamy z katalogu podany plik i wszystkie znajdujace się PO nim
        /// </summary>
        /// <param name="fileOrDirectoryName"></param>
        /// <returns></returns>
        public static MediaDirectory GetFilesFromDirectory(string fileOrDirectoryName)
        {
            //
            bool isDirectory = false;
            //
            //
            fileOrDirectoryName = System.IO.Path.GetFullPath(fileOrDirectoryName);
            string directoryName = "";
            //
            if (System.IO.Directory.Exists(fileOrDirectoryName))
            {
                directoryName = fileOrDirectoryName;
                isDirectory = true;
            }
            else
            {
                if (!System.IO.File.Exists(fileOrDirectoryName)) return new MediaDirectory();
                directoryName = System.IO.Path.GetDirectoryName(fileOrDirectoryName);
                isDirectory = false;
            }
            //
            // sprawdzamy, czy jest w cache
            foreach (MediaDirectory dc in MDQ)
            {
                if (0 == string.Compare(dc.DirectoryName, directoryName, true))
                {
                    //return dc;
                    if(isDirectory)
                    {
                        return new MediaDirectory(dc);
                    }
                    else
                    {
                        return new MediaDirectory(dc, getCuttedFileList(dc.MediaFiles, fileOrDirectoryName));
                    }
                }
            }
            //
            //List<string> ff = Directory.EnumerateFiles(directoryName, "*.*", SearchOption.TopDirectoryOnly).ToList<string>();
            //
            //
            List<MediaFile> df = getMediaFilesFromDirectory(directoryName);
            Dictionary<string, string> hintData = HintData.Load(directoryName);
            //
            //DC.Enqueue(new DirCache() { DirectoryName = directoryName, DirectoryFiles = new List<MediaFile>(df) });
            MDQ.Enqueue(new MediaDirectory() { ArgumentIsDirectory = isDirectory, DirectoryName = directoryName, MediaFiles = df, HintData = hintData });
            //
            if(isDirectory)
            {
                return new MediaDirectory(MDQ.Last());
            }
            else
            {
                return new MediaDirectory(MDQ.Last(), getCuttedFileList(MDQ.Last().MediaFiles, fileOrDirectoryName));
            }
        }
        //================================================================
        private static List<MediaFile> getMediaFilesFromDirectory(string directoryName)
        {
            int filesCount = 0;
            foreach (string f in System.IO.Directory.EnumerateFiles(directoryName, "*.*", System.IO.SearchOption.TopDirectoryOnly))
            {
                filesCount++;
            }
            //
            List<MediaFile> df = new List<MediaFile>(filesCount + 20);// więcej na wszelki wypadek
            //
            string[] files = System.IO.Directory.GetFiles(directoryName, "*.*", System.IO.SearchOption.TopDirectoryOnly);
            //
            if(!isDriveSorted(directoryName))
            {
                // na extFs nie są sortowane, ale Explorer sortuje
                Array.Sort(files, StringComparer.InvariantCultureIgnoreCase);
            }
            //
            //
            //foreach (string file in System.IO.Directory.EnumerateFiles(directoryName, "*.*", System.IO.SearchOption.TopDirectoryOnly))
            foreach (string file in files)
            {
                string resolvedName = ParseShortcut(file);
                if ("" == resolvedName) continue;
                if (!IsMediaFile(resolvedName)) continue;
                df.Add(new MediaFile() { OriginalFile = file, ResolvedFile = resolvedName });
            }
            //
            return df;
        }
        //
        //
        private static bool isDriveSorted(string dirName)
        {
            string targetDisk = Path.GetFullPath(dirName).Substring(0, 2);// UCase
            //

            DriveInfo[] allDrives = DriveInfo.GetDrives();
            foreach (DriveInfo d in allDrives)
            {
                if (targetDisk == d.Name.Substring(0, 2))
                {
                    if ("NTFS" == d.DriveFormat)
                    {
                        return true;
                    }
                    return false;
                }
            }
            //
            return false;
        }
        //
        //
        //================================================================
        private static List<MediaFile> getCuttedFileList(List<MediaFile> df, string fileName)
        {
            int n = df.FindIndex(v => v.OriginalFile == fileName);
            if (n >= 0)
            {
                MediaFile[] nDf = new MediaFile[df.Count - n];
                df.CopyTo(n, nDf, 0, nDf.Count());
                return nDf.ToList<MediaFile>();
            }
            //
            return df;
        }
        //================================================================
        public static bool IsMediaFile(string fileName)
        {
            string ext = System.IO.Path.GetExtension(fileName).ToUpper();
            //
            return null != mediaExt.FirstOrDefault(x => x == ext);
            //return ".AVI" == ext || ".MKV" == ext || ".MP4" == ext || ".VOB" == ext || ".FLV" == ext;
        }
        //================================================================
        public static string ParseShortcut(string fname)
        {
            if (0 != string.Compare(".LNK", System.IO.Path.GetExtension(fname), true)) return fname;
            Shortcut link = new Shortcut();
            link.Load(fname);
            return link.Path;
        }
        //================================================================
    }//class
}//namespace